package a3;
import java.awt.Point;
import java.util.HashMap;
import java.util.Vector;
import java.util.Random;


public class Tools {

	static Random RandomGenerator = new Random();

	/**
	 * @return one random point from a given Vector of points
	 */
	static Action randomVector( Vector<Action> v ) {
		int rnd = RandomGenerator.nextInt(v.size());
		return v.get(rnd);
	}

	/**
	 * @return the distance between two points
	 */
	static int distance(Point point1, Point point2) {
		return (int) point1.distance(point2);
	}

	/**
	 * @param number numerator of the operation
	 * @param mod modulo denominator
	 * @return modulo that is able to cope with negative numbers
	 */
	static int mod(int number, int mod) {
		return ((number % mod) + mod ) % mod;
	}

	/**
	 * subtract two points
	 */
	public static Location subLocs(Location loc1, Location loc2) {
		Location returnLoc = new Location();
		returnLoc.x =(loc1.x - loc2.x);
		returnLoc.y =(loc1.y - loc2.y);
		return returnLoc;
	}

	/**
	 * add two points
	 */
	public static Point add(Point point1, Point point2) {
		Point returnPoint = new Point();
		returnPoint.x = point1.x + point2.x;
		returnPoint.y = point1.y + point2.y;
		return returnPoint;
	}

	/**
	 * @param point numerator of the operation
	 * @param mod modulo denominator
	 * @return a point that is modulated with some value
	 */
	public static Location mod(Location loc, int mod) {
		Location returnLoc = new Location();
		returnLoc.x = mod(loc.x, mod);
		returnLoc.y = mod(loc.y, mod);
		return returnLoc;
	}

	/**
	 * @param point manhattan distance to origin
	 * @return the length of a point
	 */
	public static int length(Point point) {
		return Math.abs(point.x) + Math.abs(point.y);
	}

	/**
	 * Transforms the given position to a state representation
	 *
	 * @param position the position that will be transformed
	 * @param size the envrionment size assuming a square environment
	 * @return a state of type Point
	 */
	/*public static State positionToState(Location position, int size) {
		State returnPoint = new State();
		returnPoint.x = position.x;
		returnPoint.y = position.y;
		if(returnPoint.x > size/2)
			returnPoint.x -= size;
		if(returnPoint.x < -size/2)
			returnPoint.x += size;
		if(returnPoint.y > size/2)
			returnPoint.y -= size;
		if(returnPoint.y < -size/2)
			returnPoint.y += size;
		return returnPoint;
	}*/

		
	public static void printQ( Float[][][] Q )
	{
		for(int y = 0; y < 11; y++)
		{
			for(int x = 0; x < 11; x++)
			{
				Float maxQValue = null;
				int bestMove = -1;
				for(int move = 0; move < 5; move++)
				{
					Float QValue = Q[x][y][move];
					if( maxQValue == null )
					{
						maxQValue = QValue;
						bestMove = move;
					}
					else if( QValue > maxQValue )
					{
						maxQValue = QValue;
						bestMove = move;
					}
				}
				System.out.print(bestMovetoString(bestMove) + " ");
			}
			System.out.println();
		}
		printQValues(Q);
	}

	private static void printQValues(Float[][][] Q) {
		for(int y = 0; y < 11; y++)
		{
			for(int x = 0; x < 11; x++)
			{
				Float maxQValue = null;
				int bestMove = -1;
				for(int move = 0; move < 5; move++)
				{
					Float QValue = Q[x][y][move];
					if( maxQValue == null )
					{
						maxQValue = QValue;
						bestMove = move;
					}
					else if( QValue > maxQValue )
					{
						maxQValue = QValue;
						bestMove = move;
					}
				}
				System.out.printf("%5.2f ", maxQValue);
			}
			System.out.println();
		}
	}

	private static String bestMovetoString(int bestMove) {
		switch( bestMove )
		{
		case 0: return "^";
		case 1: return "v";
		case 2: return "<";
		case 3: return ">";
		default: return "o";
		}
	}
	
	public static Action int2Action(int actionNr)
	{
		int x, y;
		Action action = new Action();
		switch( actionNr )
		{
		case 0: x = 0; y = -1; break;
		case 1: x = 0; y = 1;break;
		case 2: x = -1; y = 0;break;
		case 3: x = 1; y = 0;break;
		default: x = 0; y = 0;
		}
		action.x = x;
		action.y = y;
		return action;
	}
	
	public static int action2int(Action a) {
		int x = a.x;
		int y = a.y;
		if(x == 0) {
			switch(y) {
				case -1: return 0; 
				case  0: return 4;
				case  1: return 1;	
			}
		} else if(x == 1){
			return 3;
		} else {
			return 2;
		}
		return 4;
	}
	
	public static float max(Float[] actions) {
		float maxValue = 0;
		for(float value: actions) {
			if(value > maxValue)
				maxValue = value;
		}
		return maxValue;
	}
 		
	
}
